# $Id: _chart.py 822 2013-06-10 07:57:48Z onealj $

from java.awt import Dimension, Color, BasicStroke, Font, GraphicsEnvironment, Dialog
from java.awt.Dialog import ModalExclusionType
from java.awt.event import ActionListener, MouseWheelListener
from java.text import DecimalFormat
from javax.swing import JFrame, Box, BoxLayout, JTabbedPane, JOptionPane, JMenuItem, JMenu

from org.jfree.chart import ChartFactory, ChartPanel, ChartMouseListener
from org.jfree.chart.axis import NumberAxis, NumberTickUnit #, SymbolAxis, DateAxis
#from org.jfree.chart.block import BlockBorder
from org.jfree.chart.labels import StandardXYToolTipGenerator #Enable to use Tool Tip 
from org.jfree.chart.plot import PlotOrientation
from org.jfree.chart.renderer.xy import XYLineAndShapeRenderer
from org.jfree.data.xy import YIntervalSeries, YIntervalSeriesCollection #, XYSeries, XYSeriesCollection, 
from org.jfree.ui import RectangleEdge, VerticalAlignment #, HorizontalAlignment, RectangleInsets, 


def setLinesVisible(chart, isvisible):
  '''temporarily show/hide plot lines (clicking on legend entry will change line visiblity)
  this is in contrast to chart.plot.getRenderer(datasetIdx).setLinesVisible(isvisible), which permanently hides/shows lines during lifetime of the chart
  handles multiple datasets if plotting on two axes'''
  for datasetIdx in range(chart.plot.datasetCount): #handle multiple datasets in case if plotting on two axes
    for seriesIdx in range(chart.plot.getDataset(datasetIdx).getSeriesCount()):
      chart.plot.getRenderer(datasetIdx).setSeriesLinesVisible(seriesIdx, isvisible)
      
def setShapesVisible(chart, isvisible):
  '''temporarily show/hide plot shapes (clicking on legend entry will change shape visiblity)
  this is in contrast to chart.plot.getRenderer(datasetIdx).setShapesVisible(isvisible), which permanently hides/shows shapes during lifetime of the chart
  handles multiple datasets if plotting on two axes'''
  for datasetIdx in range(chart.plot.datasetCount): #handle multiple datasets in case if plotting on two axes
    for seriesIdx in range(chart.plot.getDataset(datasetIdx).getSeriesCount()):
      chart.plot.getRenderer(datasetIdx).setSeriesShapesVisible(seriesIdx, isvisible)

def setGraphVisibility(chart, entity):
  #BUG: returns first result of entity.seriesKey. If there are multiple items in the legend with the same series name, this function will only bold/unbold the first matching one.
  seriesIndex = entity.dataset.indexOf(entity.seriesKey)
  try:
    line_visibility = chart.XYPlot.getRendererForDataset(entity.dataset).getSeriesLinesVisible(seriesIndex)
    shape_visibility = chart.XYPlot.getRendererForDataset(entity.dataset).getSeriesShapesVisible(seriesIndex)
    chart.XYPlot.getRendererForDataset(entity.dataset).setSeriesLinesVisible(seriesIndex, not line_visibility)
    chart.XYPlot.getRendererForDataset(entity.dataset).setSeriesShapesVisible(seriesIndex, not shape_visibility)
  except Exception, e:
    print(e)

def setGraphToBold(chart, entity):
  if 'Spec' not in str(entity.getToolTipText()): #do not bold Spec line
    if chart.XYPlot.renderer.getSeriesStroke(entity.seriesIndex).getLineWidth() == 1:
      chart.XYPlot.renderer.setSeriesStroke(entity.seriesIndex, BasicStroke(2.0))
    else:
      chart.XYPlot.renderer.setSeriesStroke(entity.seriesIndex, BasicStroke(1.0))


class MyMouseWheelListener(MouseWheelListener):

  def mouseWheelMoved(self, mousewheelevent):

    chartpanel = mousewheelevent.getComponent()
    notches = mousewheelevent.getWheelRotation()

    if mousewheelevent.isControlDown():
      #chartpanel.setMouseWheelEnabled(False) # Enable Mouse Wheel zoom
      range_current = chartpanel.chart.plot.domainAxis.getRange()
      min_current = range_current.getLowerBound()
      max_current = range_current.getUpperBound()
      range_data = chartpanel.chart.plot.getDataRange(chartpanel.chart.plot.getDomainAxis())
      min_data = range_data.getLowerBound()
      max_data = range_data.getUpperBound()
      #print min_current, max_current, min_data, max_data

      if (notches < 0): # scroll up
        print "control scroll up  by " + str(notches)
        if max_current <= max_data:
          min_current = min_current + 1 
          max_current = max_current + 1
      else:  # scroll down
        print "control scroll down  by " + str(notches)
        if min_current >= min_data:
          min_current = min_current - 1 
          max_current = max_current - 1
      chartpanel.chart.plot.domainAxis.setRange(min_current, max_current)
    else:
      #chartpanel.setMouseWheelEnabled(True) # Enable Mouse Wheel zoom
      chartpanel.setZoomInFactor(0.5)
      chartpanel.setZoomOutFactor(2)
      chartpanel.setZoomTriggerDistance(10)
      if (notches < 0): # scroll up
        print "scroll up  by " + str(notches)
        chartpanel.zoomInBoth(mousewheelevent.getX(), mousewheelevent.getY())
      else:  # scroll down      
        print "scroll down  by " + str(notches)
        chartpanel.zoomOutBoth(mousewheelevent.getX(), mousewheelevent.getY())
        

class MyMouseListener(ChartMouseListener):

  # This function gets every time there is a mouse click event 
  def chartMouseClicked(self, chartmouseevent):
    #print chartmouseevent.getEntity() # print the entity beneath the mouse click
    #print dir(chartmouseevent.getEntity()) # lists all the methods and varibles of getEntity()
    #print chartmouseevent.getTrigger() # print the mouse event that triggered this event
    #print dir(chartmouseevent.getTrigger()) # lists all the methods and varibles of getTrigger()
    #print chartmouseevent.getChart() # print the chart entity that's beneath the mouse click
    mouse_button = chartmouseevent.getTrigger().button # 1 = left mouse button, 2 = right mouse button
    mouse_click = chartmouseevent.getTrigger().clickCount # get the number of mouse clicks
    chart = chartmouseevent.getChart() # get the chart entity that's beneath the mouse 
    #print chartmouseevent.getEntity().toString()
    eventString = str(chartmouseevent.getEntity().toString())
    eventString = eventString.split(':', 1)
    if mouse_click == 2 and (mouse_button == 2 or mouse_button == 1): # if the user double-clicks using the middle or left button
      if eventString[0] == 'PlotEntity': # if the mouse isn't pointing on a trace
        chart.plot.domainAxis.setAutoRange(1) # auto-scale the x-axis first
        chart.plot.rangeAxis.setAutoRange(1) # auto-scale the y-axis second
      else:
        pass
    else:
      if eventString[0] == 'LegendItemEntity':
        setGraphVisibility(chart, chartmouseevent.getEntity())
      elif eventString[0] == 'XYItemEntity':
        setGraphToBold(chart, chartmouseevent.getEntity())


class MenuActionListener(ActionListener):
  def __init__(self, chart):
    self.chart = chart # store the chart instance
    self.myLegend = self.chart.getLegend() # store the current legend items

  def actionPerformed(self, actionevent):
    if actionevent.getActionCommand() == "Toggle Legend ON/OFF":
      if self.chart.getLegend(): # if legend exists
        self.chart.removeLegend() 
      else: # if legend doesn't exists
        self.chart.addLegend(self.myLegend)  
    if actionevent.getActionCommand() == "Move Legend to Right":
      self.myLegend.setPosition(RectangleEdge.RIGHT)
    if actionevent.getActionCommand() == "Move Legend to Left":
      self.myLegend.setPosition(RectangleEdge.LEFT)
    if actionevent.getActionCommand() == "Move Legend to Top":
      self.myLegend.setPosition(RectangleEdge.TOP)
    if actionevent.getActionCommand() == "Move Legend to Bottom":
      self.myLegend.setPosition(RectangleEdge.BOTTOM)
    if actionevent.getActionCommand() == "Set Y-axis Tick Interval":
      tick_interval = float(JOptionPane.showInputDialog(None, 'Please specify the desired y-axis tick interval:', .5))
      self.chart.plot.rangeAxis.setTickUnit(NumberTickUnit(tick_interval))
    if actionevent.getActionCommand() == "Set X-axis Tick Interval":
      tick_interval = float(JOptionPane.showInputDialog(None, 'Please specify the desired x-axis tick interval:', .5))
      self.chart.plot.domainAxis.setTickUnit(NumberTickUnit(tick_interval))
      
      
      
def create_data_set(data):
  #data_set = XYSeriesCollection()
  data_set = YIntervalSeriesCollection()
  for title, points in data:
    errorOccured = False
    #series = XYSeries(title)
    #series = XYSeries(title, 0) # set autoSort=0 (2nd arg) which allows non-functions to be plotted properly.
    series = YIntervalSeries(title, 0, 1)
    for point in points:
      #series.add(*point)
      (count,a,b,c,d) = (0,0,0,0,0)
      for i in point:
        count = count + 1
        if count == 1: a = i
        if count == 2: b = i
        if count == 3: c = i
        if count == 4: d = i
      try:
        series.add(a,b,c,d)
      except TypeError, e:
        errorOccured = True
    if errorOccured:
      print('%s: %s. Unable to add at least one point to data series %s' % (type(e), e, title))
    data_set.addSeries(series)
     
  return data_set

def create_chart(title, x_label, y_label, data_set, data_set2=YIntervalSeriesCollection()):
  '''override create_chart with data_set2 to use a dual y-axis plot'''
  chart = ChartFactory.createXYLineChart(title, x_label, y_label, data_set,
                                         PlotOrientation.VERTICAL,
                                         True,  # include legend
                                         True,  # tooltips
                                         False) # urls


  #chart.XYPlot.axisOffset = Spacer(Spacer.ABSOLUTE, 5.0, 5.0, 5.0, 5.0)
  if data_set2.seriesCount > 0:
    axis2 = NumberAxis("Return Loss Axis (dB)")
    axis2.setAutoRangeIncludesZero(False)
    chart.plot.setRangeAxis(1,axis2)
    chart.plot.setDataset(1, data_set2)
    chart.plot.mapDatasetToRangeAxis(1, 1)
  
  chart.legend.setPosition(RectangleEdge.RIGHT)
  chart.legend.setVerticalAlignment(VerticalAlignment.TOP)
  chart.legend.setItemFont(Font('Arial', Font.PLAIN, 10)) # should pick a monospaced font like Courier New? 
  
  
  colorScheme = [Color.blue, Color.red, Color.green, Color.cyan, Color.magenta, Color.orange, Color.pink]
  # http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Color.html
  #Color.orange, Color.pink, Color.yellow, Color.white, Color.black, Color.lightGrey, Color.grey, Color.darkGrey
  #brighter = [color.brighter() for color in colorScheme]
  darker =  [color.darker() for color in colorScheme]
  darkerdarker = [color.darker() for color in darker]
  #colorScheme.extend(brighter)
  colorScheme.extend(darker)
  colorScheme.extend(darkerdarker)


  for axisNum, d in enumerate([data_set, data_set2]):
    try:
      renderer = XYLineAndShapeRenderer()
      for i in range(d.seriesCount):
        seriesKey = str(d.getSeriesKey(i))
        renderer.setSeriesLinesVisible(i, True)
        renderer.setSeriesShapesVisible(i, False)
        

        #draw Spec as dashed black lines
        if 'Spec' in seriesKey:
          renderer.setSeriesStroke(i, BasicStroke(2.0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, [6,6],0))
          renderer.setSeriesPaint(i, Color.black);
          
        # elif 'CDR Predict' in seriesKey:
          # renderer.setSeriesStroke(i, BasicStroke(2))
          # renderer.setSeriesPaint(i, Color.black);
          
        #elif 'Return Loss' in seriesKey:
        #  renderer.setSeriesStroke(i, BasicStroke(1.0, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, [6,6],0))
        #  #renderer.setSeriesPaint(i, Color.black);
        
        #draw Predict as a thin grey line
        elif 'Predict' in seriesKey:
          renderer.setSeriesStroke(i, BasicStroke(0.7))
          renderer.setSeriesPaint(i, Color.gray);

        #Used by trending plots
        elif 'PwrPlan' in seriesKey or 'PosPlan' in seriesKey: #reference data
          renderer.setSeriesPaint(i, Color.gray)
        elif seriesKey.startswith('Phase 10I'): #RPT
          renderer.setSeriesPaint(i, Color(24, 167, 181).brighter()) #light teal blue (brighter)
        elif seriesKey.startswith('Phase 10O'): #RPT
          renderer.setSeriesPaint(i, Color(0, 128, 128)) # teal
        elif seriesKey.startswith('Phase 10'): #RPT
          renderer.setSeriesPaint(i, Color(24, 167, 181)) #light teal blue
        elif seriesKey.startswith('Phase 13'): #RPT
          renderer.setSeriesPaint(i, Color.green) #Color(0, 102, 51)) #starbucks green
        elif seriesKey.startswith('Phase 14'): #Pre-TV
          renderer.setSeriesPaint(i, Color(210, 180, 140)) #tan
        elif seriesKey.startswith('Phase 16'): #Summer Solstice
          renderer.setSeriesPaint(i, Color.orange) #Color(217, 135, 25)) #cool copper orange
        elif seriesKey.startswith('Phase 22'): #Winter Solstice
          renderer.setSeriesPaint(i, Color.red)
        elif seriesKey.startswith('Phase 20'): #Equinox
          renderer.setSeriesPaint(i, Color.blue) #Color(13, 79, 139)
        elif seriesKey.startswith('Phase 24'): #Post-TV
          renderer.setSeriesPaint(i, Color.green.darker().darker()) #emerald green Color(0, 201, 87)
        elif seriesKey.startswith('Phase 40'): #CATR
          renderer.setSeriesPaint(i, Color(139, 0, 139)) #dark magenta
        elif seriesKey.startswith('Phase 42'): #CATR
          renderer.setSeriesPaint(i, Color(139, 0, 139).darker()) #dark magenta
        elif seriesKey.startswith('Phase 43'): #CATR
          renderer.setSeriesPaint(i, Color(139, 0, 139).brighter()) #dark magenta
          
        else:
          renderer.setSeriesPaint(i, colorScheme[i % len(colorScheme)])
          
      tooltip = StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT, DecimalFormat("0.00"), DecimalFormat("0.00"))# create tool tip with legend and x and y values    
      renderer.setToolTipGenerator(tooltip) # set tool tip to chart
      chart.plot.setRenderer(axisNum, renderer)
      
    except Exception, e:
      print(e)
      

  
  #chart.XYPlot.renderer = renderer
  chart.XYPlot.rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits())
  
  return chart
  
  
def getSeriesCount(chart):
  '''
  returns the number of data series on a chart
  '''
  return chart.getPlot().getDataset().getSeriesCount()

#---------------------------------------------------------------------------------
class PlotFrame(JFrame):
  def __init__(self, title, x_label, y_label, data):
    #JFrame.__init__(self, title)
    self.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
    self.modalExclusionType = Dialog.ModalExclusionType.APPLICATION_EXCLUDE
    self.chart = create_chart(title, x_label, y_label, create_data_set(data))
    self.contentPane = ChartPanel(self.chart)
    add_plot_mouse(self.contentPane)
    add_plot_context_menu(self.contentPane, self.chart)

    self.contentPane.preferredSize = Dimension(800, 600)

def plot(title, x_label, y_label, data):
  frame = PlotFrame(title, x_label, y_label, data)
  frame.pack()
  frame.visible = True
  return frame
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
class BoxLayoutPlotFrame(JFrame):
  def __init__(self, frame_title, plot_info, layout_axis):
    #JFrame.__init__(self, frame_title)
    self.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
    self.modalExclusionType = Dialog.ModalExclusionType.APPLICATION_EXCLUDE
    self.charts = []

    box = Box(layout_axis)

    for title, x_label, y_label, data in plot_info:
      chart = create_chart(title, x_label, y_label, create_data_set(data))
      chartpanel = ChartPanel(chart)
      add_plot_mouse(chartpanel)
      add_plot_context_menu(chartpanel, chart)
      box.add(chartpanel)
      self.charts.append(chart)

    self.contentPane = box
    self.contentPane.preferredSize = Dimension(800, 600)

def box_layout_plot(frame_title, plot_info, layout_axis=BoxLayout.X_AXIS):
  '''creates a box and whisker plot'''
  frame = BoxLayoutPlotFrame(frame_title, plot_info, layout_axis)
  frame.pack()
  frame.visible = True
  return frame
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
class TabbedPlotFrame(JFrame):
  def __init__(self, frame_title, plot_info):
    #JFrame.__init__(self, frame_title)
    self.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
    self.modalExclusionType = Dialog.ModalExclusionType.APPLICATION_EXCLUDE
    self.charts = []

    tabs = JTabbedPane()

    for title, x_label, y_label, data in plot_info:
      chart = create_chart(title, x_label, y_label, create_data_set(data))
      chartpanel = ChartPanel(chart)
      add_plot_mouse(chartpanel)
      add_plot_context_menu(chartpanel, chart)

      tabs.addTab(title, chartpanel)
      self.charts.append(chart)
      
    self.contentPane = tabs
    self.contentPane.preferredSize = Dimension(800, 600) 
  
def tabbed_plot(frame_title, plot_info):
  maxBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds()
  frame = TabbedPlotFrame(frame_title, plot_info)
  frame.pack()
  frame.setSize(maxBounds.width, maxBounds.height)
  frame.setTitle(frame_title)
  frame.visible = True
  return frame
  
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
class TabbedPlotFrameDualAxisSpecs(JFrame):
  def __init__(self, frame_title, plot_data_left, plot_data_right, plot_info):
    #JFrame.__init__(self)
    self.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
    self.modalExclusionType = Dialog.ModalExclusionType.APPLICATION_EXCLUDE
    self.charts = []
    
    tabs = JTabbedPane()
    otabs = JTabbedPane()
    global chart
    for key in sorted(plot_data_left.keys()):
      for title, x_label, y_label in plot_info:
        chart = create_chart(title, x_label, y_label, create_data_set(plot_data_left[key][title]), create_data_set(plot_data_right[key][title]))
        chartpanel = ChartPanel(chart)
        add_plot_mouse(chartpanel)
        add_plot_context_menu(chartpanel, chart)

        tabs.addTab(title, chartpanel)
        self.charts.append(chart)

      otabs.addTab(key, tabs)
      tabs = JTabbedPane()
    self.contentPane = otabs

def tabbed_plot_dual_axis_specs(frame_title, plot_data_left, plot_data_right, plot_info):
  maxBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds()
  frame = TabbedPlotFrameDualAxisSpecs(frame_title, plot_data_left, plot_data_right, plot_info)
  frame.pack()
  frame.setSize(maxBounds.width, maxBounds.height)
  frame.setTitle(frame_title)
  frame.visible = True
  return frame
#---------------------------------------------------------------------------------

#---------------------------------------------------------------------------------
class TabbedPlotFrameSpecs(JFrame):
  def __init__(self, frame_title, plot_data, plot_info):
    #JFrame.__init__(self)
    self.defaultCloseOperation = JFrame.DISPOSE_ON_CLOSE
    self.modalExclusionType = Dialog.ModalExclusionType.APPLICATION_EXCLUDE
    self.charts = []
    
    tabs = JTabbedPane()
    otabs = JTabbedPane()
    global chart
    for key in sorted(plot_data.keys()):
      for title, x_label, y_label in plot_info:
        chart = create_chart(title, x_label, y_label, create_data_set(plot_data[key][title]))
        chartpanel = ChartPanel(chart)
        add_plot_mouse(chartpanel)
        add_plot_context_menu(chartpanel, chart)

        tabs.addTab(title, chartpanel)
        self.charts.append(chart)

      otabs.addTab(key, tabs)
      tabs = JTabbedPane()
    self.contentPane = otabs

def tabbed_plot_specs(frame_title, plot_data, plot_info):
  maxBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds()
  frame = TabbedPlotFrameSpecs(frame_title, plot_data, plot_info)
  frame.pack()
  frame.setSize(maxBounds.width, maxBounds.height)
  frame.setTitle(frame_title)
  frame.visible = True
  return frame
#---------------------------------------------------------------------------------

def add_plot_mouse(chartpanel):
  '''Description: sets default mouse settings on plot and adds mouse listener
  Side-effects: chartpanel, which is passed by reference, is modified with mouse events and a mouse listener
  Return value: not necessary. See side-effects.
  '''
  chartpanel.setMouseWheelEnabled(True) # Enable Mouse Wheel zoom
  #print chartpanel.getZoomInFactor() 
  #print chartpanel.getZoomOutFactor() 
  #print chartpanel.getZoomTriggerDistance()
  chartpanel.setMouseZoomable(True, False) # Set Mouse Zoom
  chartpanel.setFillZoomRectangle(True) # Enable the shaded zoom rectangle 
  listener = MyMouseListener() # assign a listener class
  chartpanel.addChartMouseListener(listener) # listen to the mouse click and perform certain actions

def add_plot_context_menu(chartpanel, chart):
  '''Description: Adds "Toggle Legend ON/OFF", "Legend Location", and "Set Tick Interval" items to
  right-click context menu of chart
  Side-effects: chart and chartpanel are passed by reference, so this function modifies chart and chartpanel in place
  Return value: not necessary. See side-effects.'''
  chart_menu_action_listener = MenuActionListener(chart)
  
  menu = JMenu("Set Tick Interval")
  submenu1 = JMenuItem("Set Y-axis Tick Interval") # create a new sub menu item
  submenu2 = JMenuItem("Set X-axis Tick Interval") # create a new sub menu item
  submenu1.addActionListener(chart_menu_action_listener) # assign a listener class
  submenu2.addActionListener(chart_menu_action_listener) # assign a listener class
  menu.add(submenu1) # create a sub new menu item
  menu.add(submenu2) # create a sub new menu item
  chartpanel.getPopupMenu().add(menu) # add the menu item to the current popup menu
  
  menu = JMenuItem("Toggle Legend ON/OFF") # create a new menu item
  menu.addActionListener(chart_menu_action_listener) # assign a listener class
  chartpanel.getPopupMenu().add(menu) # add the menu item to the current popup menu
  
  menu = JMenu("Legend Location")
  submenu1 = JMenuItem("Move Legend to Right") # create a new sub menu item
  submenu2 = JMenuItem("Move Legend to Left") # create a new sub menu item
  submenu3 = JMenuItem("Move Legend to Top") # create a new sub menu item
  submenu4 = JMenuItem("Move Legend to Bottom") # create a sub new menu item
  submenu1.addActionListener(chart_menu_action_listener) # assign a listener class
  submenu2.addActionListener(chart_menu_action_listener) # assign a listener class
  submenu3.addActionListener(chart_menu_action_listener) # assign a listener class
  submenu4.addActionListener(chart_menu_action_listener) # assign a listener class
  menu.add(submenu1) # create a sub new menu item
  menu.add(submenu2) # create a sub new menu item
  menu.add(submenu3) # create a sub new menu item
  menu.add(submenu4) # create a sub new menu item
  chartpanel.getPopupMenu().add(menu) # add the menu item to the current popup menu
  

def set_default_chart_display(chart):
  chart.plot.backgroundPaint = Color.white
  chart.plot.domainGridlinePaint = Color.black
  chart.plot.rangeGridlinePaint = Color.black
  chart.plot.rangeAxis.setStandardTickUnits(NumberAxis.createStandardTickUnits()) 
  chart.plot.domainAxis.setTickLabelFont(Font("Arial", Font.PLAIN, 16))
  chart.plot.rangeAxis.setTickLabelFont(Font("Arial", Font.PLAIN, 16))
  chart.plot.rangeAxis.setAutoRangeIncludesZero(False) # don't include zero as part of auto-zooming
  if getSeriesCount(chart) > 60:
    chart.removeLegend()
  #chart.plot.renderer.setShapesVisible(False)
  #chart.plot.renderer.setLinesVisible(True)
  #chart.plot.domainAxis.setInverted(1)
  #chart.plot.setDomainAxis(0,SymbolAxis("SSI",ssi_list))
  #chart.plot.renderer.setSeriesLinesVisible(0,True)
  #chart.plot.renderer.setSeriesShapesVisible(0,True)  
  
